package com.hskn.hss.module.carTrackRevise.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.Header;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hskn.hss.core.constant.Constants;
import com.hskn.hss.exception.HssException;
import com.hskn.hss.module.carTrack.entity.CarTrack;
import com.hskn.hss.module.carTrackRevise.entity.CarTrackRevise;
import com.hskn.hss.module.carTrackRevise.mapper.CarTrackReviseMapper;
import com.hskn.hss.module.carTrackRevise.service.CarTrackReviseService;
import com.hskn.hss.utils.StringUtils;
import com.hskn.hss.utils.location.GPS;
import com.hskn.hss.utils.location.GPSConverterUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author hskn
 * @since 2021-05-21
 */
@Slf4j
@Service
public class CarTrackReviseServiceImpl extends ServiceImpl<CarTrackReviseMapper, CarTrackRevise> implements CarTrackReviseService {

    @Resource
    CarTrackReviseMapper carTrackReviseMapper;
    @Autowired
    private RestTemplate restTemplate;

    /**
     * 创建轨迹
     *
     * @return
     */
    public Integer createTrack() throws HssException {
        Map paramMap = new HashMap();
        paramMap.put("key", Constants.GD_API_KEY);
        paramMap.put("sid", Constants.GD_API_SID);
        paramMap.put("tid", Constants.GD_API_TID);
        paramMap.put("trname", "轨迹" + RandomUtil.randomInt(1, 1000));
        //链式构建请求
        String result2 = HttpRequest.post(Constants.GD_API_TRACE_ADD)
                .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded")//头信息，多个头信息多次调用此方法即可
                .form(paramMap)//表单内容
                .timeout(20000)//超时，毫秒
                .execute().body();

        JSONObject result = JSONObject.parseObject(result2);
        String errcode = result.get("errcode").toString();
        if (!Constants.GD_API_RESULT_SUCCESS.equals(errcode)) {
            log.info("==createTrack,paramMap:{}", JSONObject.toJSONString(paramMap));
            throw new HssException("===高德API接口调用,创建轨迹失败,result:{}" + result.toJSONString());
        }
        Map data = (Map) result.get("data");
        Integer trid = Integer.parseInt(data.get("trid").toString());
        return trid;
    }

    /**
     * 上传轨迹信息
     *
     * @return
     */
    public void putTrack(Integer newTrid, List list) throws HssException {
        MultiValueMap<String, Object> uploadParam = new LinkedMultiValueMap<>();
        uploadParam.add("key", Constants.GD_API_KEY);
        uploadParam.add("sid", Constants.GD_API_SID);
        uploadParam.add("tid", Constants.GD_API_TID);
        uploadParam.add("trid", newTrid);
        uploadParam.add("points", list);
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/x-www-form-urlencoded");

        log.info("====上传轨迹信息:{}", JSONObject.toJSONString(uploadParam));

        HttpEntity<MultiValueMap<String, Object>> uploadEntity = new HttpEntity<>(uploadParam, headers);
        JSONObject result = restTemplate.postForObject(Constants.GD_API_TRACE_UPLOAD, uploadEntity, JSONObject.class);
        String errcode = result.get("errcode").toString();


//        Map paramMap = new HashMap();
//        paramMap.put("key", Constants.GD_API_KEY);
//        paramMap.put("sid", Constants.GD_API_SID);
//        paramMap.put("tid", Constants.GD_API_TID);
//        paramMap.put("trid", newTrid);
//        paramMap.put("points", list);
//        //链式构建请求
//        String result2 = HttpRequest.post(Constants.GD_API_TRACE_UPLOAD)
//                .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded")//头信息，多个头信息多次调用此方法即可
//                .form(paramMap)//表单内容
//                .timeout(20000)//超时，毫秒
//                .execute().body();
//
//        JSONObject result = JSONObject.parseObject(result2);
//        String errcode = result.get("errcode").toString();
        if (!Constants.GD_API_RESULT_SUCCESS.equals(errcode)) {
            throw new HssException("===高德API接口调用,轨迹点上传失败,result:" + result.toJSONString());
        }
    }

    /**
     * 查询轨迹信息
     *
     * @param newTrid
     * @param startTime
     * @param endTime
     * @throws HssException
     */
    public JSONObject getTrack(Integer newTrid, Date startTime, Date endTime) throws HssException {
        Map paramMap = new HashMap();
        paramMap.put("key", Constants.GD_API_KEY);
        paramMap.put("sid", Constants.GD_API_SID);
        paramMap.put("tid", Constants.GD_API_TID);
        paramMap.put("trid", newTrid);
        paramMap.put("starttime", startTime.getTime());
        paramMap.put("endtime", endTime.getTime());
        paramMap.put("page", 1);
        paramMap.put("pagesize", 500);
        paramMap.put("correction", "denoise=1,mapmatch=1,attribute=1,threshold=0,mode=driving");
        //链式构建请求
        String result2 = HttpRequest.post(Constants.GD_API_TRACE_SEARCH)
                .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded")//头信息，多个头信息多次调用此方法即可
                .form(paramMap)//表单内容
                .timeout(20000)//超时，毫秒
                .execute().body();
        JSONObject result = JSONObject.parseObject(result2);

        log.info("==getTrack,paramMap:{}", JSONObject.toJSONString(paramMap));
        log.info("==getTrack,result2:{}", result2);

        String errcode = result.get("errcode").toString();
        if (!Constants.GD_API_RESULT_SUCCESS.equals(errcode)) {
            throw new HssException("===高德API接口调用,查询轨迹信息失败,result:{}" + result.toJSONString());
        }
        return result;
    }

    /**
     * 删除轨迹
     *
     * @param oldTrid
     */
    public void deleteTrack(Integer oldTrid) throws HssException {
        Map paramMap = new HashMap();
        paramMap.put("key", Constants.GD_API_KEY);
        paramMap.put("sid", Constants.GD_API_SID);
        paramMap.put("tid", Constants.GD_API_TID);
        paramMap.put("trid", oldTrid);
        //链式构建请求
        String result2 = HttpRequest.post(Constants.GD_API_TRACE_DELETE)
                .header(Header.CONTENT_TYPE, "application/x-www-form-urlencoded")//头信息，多个头信息多次调用此方法即可
                .form(paramMap)//表单内容
                .timeout(20000)//超时，毫秒
                .execute().body();
        JSONObject result = JSONObject.parseObject(result2);
        String errcode = result.get("errcode").toString();
        if (!Constants.GD_API_RESULT_SUCCESS.equals(errcode)) {
            log.info("==deleteTrack,paramMap:{}", JSONObject.toJSONString(paramMap));
            throw new HssException("===高德API接口调用,删除轨迹失败,result:{}" + result.toJSONString());
        }
    }


    /**
     * 根据传入的84轨迹数据获取纠偏后的84轨迹数据
     *
     * @param limit100
     * @return
     */
    public List<CarTrackRevise> getCarTrackRevises(List<CarTrack> limit100) {
        List<CarTrackRevise> carTrackReviseList = new ArrayList<>();
        if (CollectionUtils.isEmpty(limit100)) {
            return carTrackReviseList;
        }
        Integer newTrid = null;
        try {
            /** 创建轨迹 **/
            newTrid = createTrack();
            if (null == newTrid) {
                return carTrackReviseList;
            }

            CarTrack firstCarTrack = limit100.get(0);
            String carId = firstCarTrack.getCarId();
            String eqpNum = firstCarTrack.getEqpNum();
            Date searchStartTime = firstCarTrack.getTimestamp();
            Date searchEndTime = limit100.get(limit100.size() - 1).getTimestamp();

            List list = new ArrayList();
            for (int i = 0; i < limit100.size(); i++) {
                CarTrack carTrack = limit100.get(i);
                String lat = carTrack.getLat();
                String lng = carTrack.getLng();
                //84坐标转为高德坐标
                GPS gps = GPSConverterUtils.gps84_To_Gcj02(Double.parseDouble(lat), Double.parseDouble(lng));

                DecimalFormat df = new DecimalFormat("#.000000");
                JSONObject json = new JSONObject();
                JSONObject props = new JSONObject();
                props.put("extra",
                        "{'car_id':'" + carTrack.getCarId() +
                                "','eqp_num':'" + carTrack.getEqpNum() +
                                "','oil_mass':'" + carTrack.getOilMass() +
//                                "','facility_id':'" + (StringUtils.isEmpty(carTrack.getFacilityId()) ? "" : carTrack.getFacilityId()) +
                                "','address':'" + carTrack.getAddress() +
                                "','speed':'" + carTrack.getSpeed() +
                                "'}");
                json.put("location", df.format(gps.getLon()) + "," + df.format(gps.getLat()));
                json.put("locatetime", carTrack.getTimestamp().getTime());
                json.put("props", props);
                list.add(json);
            }

            /** 上传轨迹信息 **/
            putTrack(newTrid, list);
            /** 查询轨迹信息 **/
            JSONObject result = getTrack(newTrid, searchStartTime, searchEndTime);

            DecimalFormat df = new DecimalFormat("#.000000");
            Date currentDate = new Date();
            Object dataObj = result.get("data");
            if (null == dataObj) {
                return carTrackReviseList;
            }
            Map data = (Map) dataObj;
            Object tracksObj = data.get("tracks");
            if (null == tracksObj) {
                return carTrackReviseList;
            }
            List tracks = (List) tracksObj;
            Map track = (Map) tracks.get(0);
            List<Map> points = (List) track.get("points");
            for (Map pointObj : points) {
                CarTrackRevise carTrackRevise = new CarTrackRevise();
                carTrackRevise.setCreateTime(currentDate);
                carTrackRevise.setSpeed(0);
                carTrackRevise.setOilMass(0d);

                String location = pointObj.get("location").toString();
                String[] locationSplit = location.split(",");
                //高德坐标转84坐标
                GPS gps = GPSConverterUtils.gcj_To_Gps84(Double.parseDouble(locationSplit[1]), Double.parseDouble(locationSplit[0]));
                String locatetime = pointObj.get("locatetime").toString();
                Object props = pointObj.get("props");
                if (null != props) {
                    Map propsObj = (Map) props;
                    String extra = propsObj.get("extra").toString();
                    JSONObject extraObj = JSONObject.parseObject(extra, JSONObject.class);
                    String car_id = extraObj.getString("car_id");
                    String eqp_num = extraObj.getString("eqp_num");
                    String oil_mass = extraObj.getString("oil_mass");
                    String facility_id = extraObj.getString("facility_id");
                    String address = extraObj.getString("address");
                    String speed = extraObj.getString("speed");
                    carTrackRevise.setAddress(address);
                    carTrackRevise.setOilMass(Double.parseDouble(oil_mass));
                    carTrackRevise.setFacilityId(facility_id);
                    carTrackRevise.setSpeed(new Double(Double.parseDouble(speed)).intValue());
                }
                carTrackRevise.setCarId(carId);
                carTrackRevise.setEqpNum(eqpNum);
                carTrackRevise.setTimestamp(DateUtil.date(Long.parseLong(locatetime)));
                carTrackRevise.setLat(df.format(gps.getLat()));
                carTrackRevise.setLng(df.format(gps.getLon()));
                carTrackReviseList.add(carTrackRevise);
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        } finally {
            if (null != newTrid) {
                /** 删除轨迹 **/
                try {
                    deleteTrack(newTrid);
                } catch (HssException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return carTrackReviseList;
    }

    @Override
    public void handleCarTrackRevise(List<CarTrack> limit100) {
        List<CarTrackRevise> carTrackReviseList = getCarTrackRevises(limit100);
        if (!CollectionUtils.isEmpty(carTrackReviseList)) {
            log.info("===={}条车辆轨迹，调用高德获取到的数量：{}", limit100.size(), carTrackReviseList.size());
            //批量保存纠偏数据
            saveBatch(carTrackReviseList);
        }
    }

    @Override
    public List mList(JSONObject params) throws HssException {

        JSONObject json = new JSONObject();
        //车辆轨迹queryWrapper
        QueryWrapper<CarTrackRevise> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByAsc(CarTrackRevise::getTimestamp);
        String carId = params.getString("carId");
        if (StringUtils.isNotEmpty(carId)) {
            //车辆轨迹queryWrapper
            queryWrapper.lambda().eq(CarTrackRevise::getCarId, carId);
        }
        String starttime = params.getString("starttime");
        String endtime = params.getString("endtime");
        if (StringUtils.isNotEmpty(starttime) && StringUtils.isNotEmpty(endtime)) {
            //车辆轨迹queryWrapper
            queryWrapper.lambda().between(CarTrackRevise::getTimestamp, starttime, endtime);
        }
        //车辆轨迹queryWrapper
        List<CarTrackRevise> carTrackList = carTrackReviseMapper.selectList(queryWrapper);

        return carTrackList;
    }

}
